home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 49 / Amiga Format CD49 (2000-01-17)(Future Publishing)(GB)(Track 1 of 3)[!][issue 2000-02].iso / -serious- / misc / mmulib / c_sources / musetcachemode.c < prev    next >
C/C++ Source or Header  |  1999-11-29  |  22KB  |  448 lines

  1. /*****************************************************************
  2.  ** MuSetCacheMode                                              **
  3.  **                                                             **
  4.  ** Reprogram MMU tables selectively.                           **
  5.  ** Release 40.6, © 1999 THOR-Software inc.                     **
  6.  ** 9.8.1999 Thomas Richter                                     **
  7.  *****************************************************************/
  8.  
  9. /// Includes
  10. #include <exec/types.h>
  11. #include <exec/memory.h>
  12. #include <exec/ports.h>
  13. #include <dos/dos.h>
  14. #include <mmu/mmubase.h>
  15. #include <mmu/context.h>
  16. #include <mmu/mmutags.h>
  17. #include <workbench/startup.h>
  18.  
  19. #include <thor/conversions.h>
  20.  
  21. #include <proto/exec.h>
  22. #include <proto/mmu.h>
  23. #include <proto/dos.h>
  24. #include <proto/icon.h>
  25. #include <string.h>
  26. ///
  27. /// Defines
  28. #define STRINGDATE "8.8.99"
  29. #define STRINGVERSION "40.6"
  30. #define TEMPLATE "ADDRESS=FROM/A,SIZE/A,COPYBACK/S,WRITETHROUGH/S,NOCACHESERIALIZED=CACHEINHIBIT/S,NONSERIAL/S,NOCACHE=IMPRECISE/S,VALID/S,INVALID/S,BLANK/S,IO=IOSPACE/S,NOIO=NOIOSPACE/S,ROM/S,NOROM/S,WRITEPROTECTED/S,NOTWRITEPROTECTED/S,USERONLY/S,SUPERVISORONLY/S,VERBOSE/S"
  31. #define CACHEFLAGS (MAPP_CACHEINHIBIT|MAPP_NONSERIALIZED|MAPP_IMPRECISE|MAPP_COPYBACK)
  32. #define ROMFLAGS (MAPP_ROM|MAPP_WRITEPROTECTED)
  33.  
  34. #define OPT_ADDRESS 0
  35. #define OPT_SIZE 1
  36. #define OPT_COPYBACK 2
  37. #define OPT_WRITETHROUGH 3
  38. #define OPT_NOCACHE 4
  39. #define OPT_NOCACHESERIALIZED 5
  40. #define OPT_NOCACHEIMPRECISE 6
  41. #define OPT_VALID 7
  42. #define OPT_INVALID 8
  43. #define OPT_BLANK 9
  44. #define OPT_IO 10
  45. #define OPT_NOIO 11
  46. #define OPT_ROM 12
  47. #define OPT_NOROM 13
  48. #define OPT_WRITEPROTECTED 14
  49. #define OPT_NOTWRITEPROTECTED 15
  50. #define OPT_USERONLY 16
  51. #define OPT_SUPERVISORONLY 17
  52. #define OPT_VERBOSE 18
  53. #define OPT_WINDOW 19
  54. #define OPT_COUNT 20
  55.  
  56. #define WHICH_ALL       3
  57. #define WHICH_USER      1
  58. #define WHICH_SUPER     2
  59. ///
  60. /// Statics
  61. struct MMUBase *MMUBase;
  62. struct DosLibrary *DOSBase;
  63. struct ExecBase *SysBase;
  64. struct Library *IconBase;
  65. ///
  66. /// Protos
  67. int __asm __saveds main(void);
  68. int SetCacheMode(ULONG from,ULONG size,ULONG flags,ULONG mask,ULONG which);
  69. struct RDArgs *ReadTTArgs(struct WBStartup *msg,LONG args[],struct RDArgs **tmp);
  70. int SetCache(struct MMUContext *ctx,ULONG from,ULONG size,ULONG flags,ULONG mask);
  71. ///
  72.  
  73. char version[]="$VER: MuSetCacheMode " STRINGVERSION " (" STRINGDATE ") © THOR";
  74.  
  75. /// main
  76. int __asm __saveds main(void)
  77. {
  78. LONG args[OPT_COUNT];
  79. struct RDArgs *rd,*myrd;
  80. struct Process *proc;
  81. int rc=20;
  82. LONG err;
  83. struct WBStartup *msg;
  84. BPTR oldout;
  85. struct MsgPort *oldconsole;
  86. LONG flags,which;
  87. char *whichmsg;
  88. int from=0,size=0;
  89. ULONG mask;
  90. char flagsmsg[256];
  91.  
  92.  
  93.         SysBase=*((struct ExecBase **)(4L));
  94.  
  95.         memset(args,0,sizeof(LONG)*OPT_COUNT);
  96.         flagsmsg[0]='\0';                       /* Clear this string */
  97.  
  98.         /* Wait for the workbench startup, if any */
  99.         proc=(struct Process *)FindTask(NULL);
  100.  
  101.         if (!(proc->pr_CLI)) {
  102.                 WaitPort(&(proc->pr_MsgPort));
  103.                 msg=(struct WBStartup *)GetMsg(&(proc->pr_MsgPort));
  104.         } else  msg=NULL;
  105.  
  106.         if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) {
  107.                 if (MMUBase=(struct MMUBase *)OpenLibrary("mmu.library",0L)) {
  108.  
  109.                         err=ERROR_REQUIRED_ARG_MISSING;
  110.  
  111.                         myrd=NULL;      /* reset the temporary ReadArgs */
  112.                         oldout=NULL;
  113.                         oldconsole=NULL;
  114.                         if (msg) {
  115.                                 oldout=SelectOutput(NULL);
  116.                                 oldconsole=SetConsoleTask(NULL);
  117.                                 rd=ReadTTArgs(msg,args,&myrd);
  118.                         } else  rd=ReadArgs(TEMPLATE,args,NULL);
  119.  
  120.                         if (rd) {
  121.                                 if (!GetMMUType()) {
  122.                                         Printf("MuSetCacheMode requires a working MMU.\n");
  123.                                         err=10;
  124.                                 } else {
  125.  
  126.                                         err=0;
  127.  
  128.                                         if (args[OPT_ADDRESS]==NULL || args[OPT_SIZE]==NULL)
  129.                                                 err=ERROR_REQUIRED_ARG_MISSING;
  130.  
  131.                                         if (err==0) {
  132.  
  133.                                                 if (!StrToL((char *)(args[OPT_ADDRESS]),NULL,&from,16))
  134.                                                         err=ERROR_BAD_NUMBER;
  135.  
  136.                                                 if (!StrToL((char *)(args[OPT_SIZE]),NULL,&size,16)) {
  137.                                                         err=ERROR_BAD_NUMBER;
  138.                                                 } else if (size==0) err=ERROR_BAD_NUMBER;
  139.  
  140.  
  141.                                         }       
  142.                                         if (err==0) {
  143.  
  144.                                                 flags=0;
  145.                                                 mask=0;
  146.  
  147.                                                 if (args[OPT_VALID]) {
  148.                                                         mask |= MAPP_INVALID | MAPP_BLANK | MAPP_REPAIRABLE;
  149.                                                         strcat(flagsmsg,"valid ");
  150.                                                 }
  151.                                                 if (args[OPT_IO]) {
  152.                                                         flags &= ~CACHEFLAGS;
  153.                                                         flags |= MAPP_IO|MAPP_CACHEINHIBIT;
  154.                                                         mask |= MAPP_IO|CACHEFLAGS;
  155.                                                         strcat(flagsmsg,"IO space ");
  156.                                                 }
  157.                                                 if (args[OPT_NOIO]) {
  158.                                                         mask |= MAPP_IO;
  159.                                                         flags &= ~MAPP_IO;
  160.                                                         strcat(flagsmsg,"memory space ");
  161.                                                 }
  162.                                                 if (args[OPT_COPYBACK]) {
  163.                                                         flags &= ~CACHEFLAGS;
  164.                                                         flags |= MAPP_COPYBACK;
  165.                                                         mask |= CACHEFLAGS;
  166.                                                         strcat(flagsmsg,"copyback ");
  167.                                                 }
  168.                                                 if (args[OPT_WRITETHROUGH]) {
  169.                                                         flags &= ~CACHEFLAGS;    /* writethrough is the default */
  170.                                                         mask |= CACHEFLAGS;
  171.                                                         strcat(flagsmsg,"writethrough ");
  172.                                                 }
  173.                                                 if (args[OPT_NOCACHE]) {
  174.                                                         flags &= ~CACHEFLAGS;
  175.                                                         flags |= MAPP_CACHEINHIBIT;
  176.                                                         mask |= CACHEFLAGS;
  177.                                                         strcat(flagsmsg,"cacheinhibit ");
  178.                                                 }
  179.                                                 if (args[OPT_NOCACHESERIALIZED]) {
  180.                                                         flags &= ~CACHEFLAGS;
  181.                                                         flags |= MAPP_CACHEINHIBIT | MAPP_NONSERIALIZED;
  182.                                                         mask |= CACHEFLAGS;
  183.                                                         strcat(flagsmsg,"cacheinhibit non-serialized ");
  184.                                                 }
  185.                                                 if (args[OPT_NOCACHEIMPRECISE]) {
  186.                                                         flags &= ~CACHEFLAGS;
  187.                                                         flags |= MAPP_CACHEINHIBIT | MAPP_IMPRECISE;
  188.                                                         mask |= CACHEFLAGS;
  189.                                                         strcat(flagsmsg,"cacheinhibit imprecise ");
  190.                                                 }
  191.                                                 if (args[OPT_ROM]) {
  192.                                                         flags &= ~ROMFLAGS;
  193.                                                         flags |= MAPP_ROM;
  194.                                                         mask |= ROMFLAGS;
  195.                                                         strcat(flagsmsg,"ROM ");
  196.                                                 }
  197.                                                 if (args[OPT_NOROM]) {
  198.                                                         mask |= MAPP_ROM;
  199.                                                         flags &= ~MAPP_ROM;
  200.                                                         strcat(flagsmsg,"no ROM ");
  201.                                                 }
  202.                                                 if (args[OPT_WRITEPROTECTED]) {
  203.                                                         flags &= ~ROMFLAGS;
  204.                                                         flags |= MAPP_WRITEPROTECTED;
  205.                                                         mask |= ROMFLAGS;
  206.                                                         strcat(flagsmsg,"read only ");
  207.                                                 }
  208.                                                 if (args[OPT_NOTWRITEPROTECTED]) {
  209.                                                         mask |= MAPP_WRITEPROTECTED;
  210.                                                         flags &= ~MAPP_WRITEPROTECTED;
  211.                                                         strcat(flagsmsg,"read/write ");
  212.                                                 }
  213.                                                 if (args[OPT_INVALID]) {
  214.                                                         mask = 0xffffffff;
  215.                                                         flags = MAPP_INVALID | MAPP_REPAIRABLE;
  216.                                                         strcpy(flagsmsg,"invalid ");
  217.                                                 }
  218.                                                 if (args[OPT_BLANK]) {
  219.                                                         mask = 0xffffffff;
  220.                                                         flags = MAPP_BLANK;
  221.                                                         strcpy(flagsmsg,"blank ");
  222.                                                 }
  223.                                                 which=WHICH_ALL;
  224.                                                 whichmsg = "user and supervisor";
  225.                                                 if (args[OPT_USERONLY]) {
  226.                                                         which = WHICH_USER;
  227.                                                         whichmsg = "user";
  228.                                                 }
  229.                                                 if (args[OPT_SUPERVISORONLY]) {
  230.                                                         which=WHICH_SUPER;
  231.                                                         whichmsg = "supervisor";
  232.                                                 }
  233.  
  234.                                                 if (flagsmsg[0]=='\0') {
  235.                                                         err=ERROR_REQUIRED_ARG_MISSING;
  236.                                                 } else {
  237.                                                         err=SetCacheMode((ULONG)from,(LONG)size,flags,mask,which);
  238.                                                         if ((err==0) && args[OPT_VERBOSE]) {
  239.                                                                 Printf("%s.\n"
  240.                                                                        "Set %s mode from 0x%lx, size 0x%lx to %s\n",
  241.                                                                        version+6,whichmsg,from,size,flagsmsg);
  242.                                                         }
  243.                                                 }
  244.                                         }
  245.                                 }
  246.  
  247.                                 FreeArgs(rd);
  248.                                 if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  249.                                 if (msg)  Close(SelectOutput(NULL));
  250.                         } else  err=IoErr();
  251.  
  252.                         if (msg) {
  253.                                 SelectOutput(oldout);
  254.                                 SetConsoleTask(oldconsole);
  255.                         }
  256.  
  257.                         if (err<64) {
  258.                                 rc=err;
  259.                                 err=0;
  260.                         } else {
  261.                                 if (!msg) PrintFault(err,"MuSetCacheMode failed");
  262.                                 rc=10;
  263.                         }
  264.                         SetIoErr(err);
  265.  
  266.                         CloseLibrary((struct Library *)MMUBase);
  267.                 } else PrintFault(ERROR_OBJECT_NOT_FOUND,"MuSetCacheMode requires the mmu.library");
  268.                 CloseLibrary((struct Library *)DOSBase);
  269.         }
  270.  
  271.         return rc;
  272. }
  273. ///
  274. /// ReadTTArgs
  275. struct RDArgs *ReadTTArgs(struct WBStartup *msg,LONG args[],struct RDArgs **tmp)
  276. {
  277. struct WBArg *wbarg;
  278. struct DiskObject *dop;
  279. char **tt;                      /* ToolTypes array */
  280. char *wbstr;                    /* Our self-made workbench argument string */
  281. char *here;
  282. BPTR oldlock;
  283. ULONG len;
  284. struct RDArgs *rd=NULL,*myrd=NULL;
  285. LONG err=0;
  286. BPTR newout;
  287.  
  288.         if (IconBase=OpenLibrary("icon.library",37L)) {
  289.                 if (wbarg=msg->sm_ArgList) {
  290.                         /* use a project icon if there is one... */
  291.                         if (msg->sm_NumArgs > 1) wbarg++;
  292.  
  293.                         /* go into the directory */
  294.                         oldlock=CurrentDir(wbarg->wa_Lock);
  295.  
  296.                         if (dop=GetDiskObject(wbarg->wa_Name)) {
  297.                                 if (tt=dop->do_ToolTypes) {
  298.                                         /* Read a special tool type for the output window */
  299.  
  300.                                         /* Calc the size of the argument string */
  301.  
  302.                                         len = 3;        /* reserve space for SPC,LF,NUL */
  303.                                         while (*tt) {
  304.                                                 len += strlen(*tt)+1;   /* string, plus space */
  305.                                                 tt++;
  306.                                         }
  307.  
  308.                                         if (wbstr=AllocVec(len,MEMF_PUBLIC)) {
  309.                                                 /* Now copy the arguments into this string, one by one
  310.                                                    and check whether the argument string is still valid. */
  311.  
  312.                                                 tt=dop->do_ToolTypes;
  313.                                                 here=wbstr;
  314.                                                 do{
  315.                                                         *here='\0';                     /* terminate string */
  316.                                                         /* Check whether this tool type is
  317.                                                            commented out. Just ignore it in this case */
  318.                                                         if (*tt) {
  319.                                                                 if (**tt=='(' || **tt==';')
  320.                                                                         continue;
  321.  
  322.                                                                 strcpy(here,*tt);      /* Add TT string */
  323.                                                         }
  324.                                                         len=strlen(here);
  325.                                                         here[len]='\n';
  326.                                                         here[len+1]='\0';               /* terminate string */
  327.  
  328.                                                         /* Now try to ReadArg' this string */
  329.  
  330.                                                         /* release old arguments left over from last loop */
  331.                                                         if (rd) FreeArgs(rd);
  332.                                                         if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  333.                                                         rd=NULL;
  334.                                                         memset(args,0,sizeof(LONG)*OPT_COUNT);
  335.  
  336.                                                         if (myrd=AllocDosObject(DOS_RDARGS,NULL)) {
  337.                                                                 /* Allocate and setup the ReadArgs source */
  338.                                                                 myrd->RDA_Source.CS_Buffer=wbstr;
  339.                                                                 myrd->RDA_Source.CS_Length=strlen(wbstr);
  340.  
  341.                                                                 if (rd=ReadArgs(TEMPLATE ",WINDOW/K",args,myrd)) {
  342.                                                                         /* Is this still valid? */
  343.                                                                         here[len]=' ';
  344.                                                                         here+=len+1;
  345.                                                                         /* if so, accept this argument and go on */
  346.                                                                 } else {
  347.                                                                         err=IoErr();
  348.                                                                         if (err==ERROR_NO_FREE_STORE) break;
  349.                                                                         else    err=0;  /* Ignore unknown or invalid arguments silently */
  350.                                                                 }
  351.                                                         } else {
  352.                                                                 err=ERROR_NO_FREE_STORE;
  353.                                                                 break;
  354.                                                         }
  355.                                                 }while(*tt++);
  356.  
  357.                                                 FreeVec(wbstr);
  358.                                         } else err=ERROR_NO_FREE_STORE;
  359.                                 } else err=ERROR_REQUIRED_ARG_MISSING; /* Huh, how should this happen ? */
  360.                                 FreeDiskObject(dop);
  361.                         } else err=IoErr();
  362.                         CurrentDir(oldlock);
  363.                 } else err=ERROR_REQUIRED_ARG_MISSING; /* This should not happen either */
  364.                 CloseLibrary(IconBase);
  365.         } else err=ERROR_OBJECT_NOT_FOUND;    /* This should not happen */
  366.  
  367.         /* Open an output stream */
  368.  
  369.         if (err==0) {
  370.                 if (newout=Open((args[OPT_WINDOW])?((char *)args[OPT_WINDOW]):("NIL:"),MODE_NEWFILE)) {
  371.                         SelectOutput(newout);
  372.                         /* Hack in the output console. Well, well... */
  373.                         SetConsoleTask(((struct FileHandle *)(BADDR(newout)))->fh_Type);
  374.                 } else err=IoErr();
  375.         }
  376.  
  377.         if (err) {
  378.                 if (rd)   FreeArgs(rd);
  379.                 if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  380.                 SetIoErr(err);
  381.                 rd=NULL;
  382.                 myrd=NULL;
  383.         }
  384.  
  385.         *tmp=myrd;
  386.         return rd;
  387. }
  388. ///
  389. /// SetCacheMode
  390. int SetCacheMode(ULONG from,ULONG size,ULONG flags,ULONG mask,ULONG which)
  391. {
  392. struct MMUContext *ctx,*sctx;   /* default context, supervisorcontext */
  393. ULONG psize;
  394. int err;
  395.  
  396.         ctx=DefaultContext();   /* get the default context */
  397.         sctx=SuperContext(ctx); /* get the supervisor context for this one */
  398.  
  399.         psize=GetPageSize(ctx);
  400.         if (size & (psize-1)) {
  401.                 Printf("The given size 0x%lx is not divisible by the page size 0x%lx.\n",size,psize);
  402.                 return ERROR_BAD_NUMBER;
  403.         }
  404.         if (from & (psize-1)) {
  405.                 Printf("The given address 0x%lx is not divisible by the page size 0x%lx.\n",from,psize);
  406.                 return ERROR_BAD_NUMBER;
  407.         }
  408.         if (psize!=GetPageSize(sctx)) {
  409.                 Printf("MuSetCacheMode does not support different user and supervisor page sizes.\n");
  410.                 return ERROR_OBJECT_WRONG_TYPE;
  411.         }
  412.  
  413.         if (which & WHICH_USER) {
  414.                 if (err=SetCache(ctx,from,size,flags,mask))
  415.                         return err;
  416.         }
  417.  
  418.         if (which & WHICH_SUPER) {
  419.                 if (err=SetCache(sctx,from,size,flags,mask))
  420.                         return err;
  421.         }
  422.  
  423.         return 0;
  424. }
  425. ///
  426. /// SetCache
  427. int SetCache(struct MMUContext *ctx,ULONG from,ULONG size,ULONG flags,ULONG mask)
  428. {
  429. struct MinList *ctxl;
  430.  
  431.         if (ctxl=GetMapping(ctx)) {
  432.          if (SetProperties(ctx,flags,mask,from,size,TAG_DONE)) {
  433.           if (RebuildTree(ctx)) {
  434.                   ReleaseMapping(ctx,ctxl);
  435.                   return 0;     /* Everything worked fine */
  436.           } /* the MMU tree could not be build. It is unmodified in this case */
  437.          }
  438.          /* Re-install the old properties. This can't fail. */
  439.  
  440.          SetPropertyList(ctx,ctxl);
  441.          ReleaseMapping(ctx,ctxl);
  442.         }
  443.  
  444.         return ERROR_NO_FREE_STORE;
  445. }
  446. ///
  447.  
  448.